package com.profound.notes.component;

import ohos.agp.components.*;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;

import static com.profound.notes.component.Recycler.DIRECTION_DOWN;
import static com.profound.notes.component.Recycler.DIRECTION_UP;

/**
 * @author zjwujlei
 * @date 2021/4/24
 * @email zjwujlei@sina.com
 * @description
 */
public class SpanLayout extends ComponentContainer implements ComponentContainer.EstimateSizeListener,
        ComponentContainer.ArrangeListener, Component.CanAcceptScrollListener, Component.ScrolledListener, Component.TouchEventListener, Component.DraggedListener {

    private Recycler mRecycler;
    private SpanLayoutManager mLayoutManager;
    private int mColumnNum = 2;

    private int startY = 0;
    private int scrollY = 0;
    private int mDirection = DIRECTION_UP;
    private boolean mChange = false;

    private BaseItemProvider mProvider;
    public SpanLayout(Context context) {
        super(context);
        setEstimateSizeListener(this);
        setArrangeListener(this);
        setCanAcceptScrollListener(this);
        setScrolledListener(this);
        setTouchEventListener(this);
        setDraggedListener(DRAG_VERTICAL,this);
        setAutoLayout(true);
    }

    public SpanLayout(Context context, AttrSet attrSet) {
        super(context, attrSet);
    }

    public SpanLayout(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
    }


    public void setItemProvider(BaseItemProvider provider){
        mProvider = provider;
        mRecycler = new Recycler(this,mProvider);
        if(mLayoutManager != null){
            mLayoutManager.setProvider(mProvider);
            mLayoutManager.setRecycler(mRecycler);
        }
    }

    public void setLayoutManager(SpanLayoutManager manager){
        mLayoutManager = manager;
        mLayoutManager.setProvider(mProvider);
        mLayoutManager.setRecycler(mRecycler);
        mLayoutManager.setSpanLayout(this);

    }

    public BaseItemProvider getItemProvider(){
        return mProvider;

    }

    public void setColumnNum(int columnNum){
        mColumnNum = columnNum;
    }

    @Override
    public boolean onEstimateSize(int widthEstimatedConfig, int heightEstimatedConfig) {
        int width = Component.EstimateSpec.getSize(widthEstimatedConfig);
        int height = Component.EstimateSpec.getSize(heightEstimatedConfig);
        setEstimatedSize(
                Component.EstimateSpec.getChildSizeWithMode(width, widthEstimatedConfig, EstimateSpec.UNCONSTRAINT),
                Component.EstimateSpec.getChildSizeWithMode(height, heightEstimatedConfig, EstimateSpec.UNCONSTRAINT));
        mLayoutManager.setEstimateSize(widthEstimatedConfig,heightEstimatedConfig);
//        measureChild(widthEstimatedConfig,heightEstimatedConfig);
        return true;
    }

    public void measureChild(int widthEstimatedConfig, int heightEstimatedConfig){

        int width = Component.EstimateSpec.getSize(widthEstimatedConfig);
        int childWidth = width / mColumnNum;
        for(RecyclerItem item:mRecycler.getAttachedScrap()){
            if(item.width == 0 && item.child != null){
                ComponentContainer.LayoutConfig lc = item.child.getLayoutConfig();
                int childWidthMeasureSpec = Component.EstimateSpec.getChildSizeWithMode(
                        childWidth - lc.getMarginLeft() - lc.getMarginRight(), getEstimatedWidth(), Component.EstimateSpec.PRECISE);
                int childHeightMeasureSpec = Component.EstimateSpec.getChildSizeWithMode(
                        lc.height, getEstimatedHeight(), Component.EstimateSpec.UNCONSTRAINT);
                item.child.estimateSize(childWidthMeasureSpec, childHeightMeasureSpec);
                item.width = childWidth - lc.getMarginLeft() - lc.getMarginRight();
                item.height = item.child.getEstimatedHeight();
                item.marginLeft = lc.getMarginLeft();
                item.marginTop = lc.getMarginTop();
                item.marginRight = lc.getMarginRight();
                item.marginBottom = lc.getMarginBottom();
            }
        }
    }





    @Override
    public boolean onArrange(int left, int top, int width, int height) {


        //第一次fill，从item0开始一直到leftHeight和rightHeight都大于height为止。
        if(mRecycler.getAttachedScrap().isEmpty()){
           mLayoutManager.fill(left,top,left+width,top+height,DIRECTION_UP);
        }
//        removeAllComponents(); //调用removeAllComponents的话会一直出发重新绘制。
        for(RecyclerItem item:mRecycler.getAttachedScrap()){
            item.child.arrange(item.positionX+item.marginLeft,scrollY+item.positionY+item.marginTop,item.width,item.height);
        }
        return true;
    }

    @Override
    public boolean canAcceptScroll(Component component, int i, boolean b) {
        return false;
    }

    @Override
    public void onContentScrolled(Component component, int i, int i1, int i2, int i3) {
    }

    @Override
    public void scrolledStageUpdate(Component component, int newStage) {
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        return true;
    }

    @Override
    public void onDragDown(Component component, DragInfo dragInfo) {

    }



    @Override
    public void onDragStart(Component component, DragInfo dragInfo) {
        startY = dragInfo.startPoint.getPointYToInt();
    }

    @Override
    public void onDragUpdate(Component component, DragInfo dragInfo) {
        int dt = dragInfo.updatePoint.getPointYToInt() - startY;
        int tryScrollY = dt + scrollY;
        startY = dragInfo.updatePoint.getPointYToInt();
        mDirection = dt<0?DIRECTION_UP:DIRECTION_DOWN;
        mChange = mLayoutManager.fill(0, -tryScrollY,getEstimatedWidth(),-tryScrollY+getEstimatedHeight(),mDirection);
        if(mChange){
            scrollY = tryScrollY;
            postLayout();
        }


    }

    @Override
    public boolean onDrag(Component component, DragEvent event) {

        return super.onDrag(component, event);
    }

    @Override
    public void onDragEnd(Component component, DragInfo dragInfo) {
    }

    @Override
    public void onDragCancel(Component component, DragInfo dragInfo) {
    }

    @Override
    public boolean onDragPreAccept(Component component, int dragDirection) {
        return true;
    }

}
